﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;

#region IMLibrary

using IMLibrary.Net.Enum; 
using IMLibrary.BinaryPacket;
using Ourmsg.NetClient;

using IMLibrary.WS;
using IMLibrary.Net; 

#endregion

namespace Ourmsg.FileTransmit
{
    /// <summary>
    /// Tcp离线文件传输客户端
    /// </summary>
    public class OfflineFileClientV1 : FileTransmitBaseV1 
    {
        #region 构造 
        public OfflineFileClientV1(TFileInfo tFileInfo, string serverIP, int port,bool isSend)
            : base(tFileInfo, serverIP, port, isSend)
        {
            mtu = 20000;//1次下载25K 
            tFileInfo.IsSend = IsSend;
            if (!isSend)
            {
                ///创建接收文件夹
                System.IO.DirectoryInfo dInfo = new System.IO.DirectoryInfo("ReceivedFile");
                if (!dInfo.Exists)
                    dInfo.Create();
                dInfo = null;
                ///创建接收缓存文件夹
                dInfo = new System.IO.DirectoryInfo("FileCache");
                if (!dInfo.Exists)
                    dInfo.Create();
                dInfo = null;
                CacheFile = "FileCache\\" + TFileInfo.MD5;
            }

            if (wsClient == null)
            {
                wsClient = new WebSocket(string.Format("ws://{0}:{1}/OfflineFiles", serverIP, port));
                wsClient.SetCredentials("Ourmsg", "123456@Ourmsg.net", true);
                //wsClient.OnClose += WsClient_OnClose;
                wsClient.OnOpen += WsClient_OnOpen;
                wsClient.OnMessage += WsClient_OnMessage;
              
            }
        }
        #endregion

        #region 事件
        /// <summary>
        /// 文件正被其他人传输...
        /// </summary>
        public event TransmitEventHandler  ElseTransmiting;
        /// <summary>
        /// 文件正被其他人传输...事件
        /// </summary>
        protected virtual void OnElseTransmiting()
        {
            if ( ElseTransmiting != null)
                ElseTransmiting(this, new fileTransmitEvnetArgs(TFileInfo));
        }
        #endregion

        #region 变量  
        /// <summary>
        /// 
        /// </summary>
        System.Timers.Timer timer = null; 
        /// <summary>
        /// 
        /// </summary>
        WebSocket wsClient = null;
        /// <summary>
        /// 
        /// </summary>
        bool Connectioned = false;
        #endregion

        #region TCP操作

        #region strat
        /// <summary>
        /// 
        /// </summary>
        public void Start()
        {
            wsClient.ConnectAsync(); 
            buffer =new byte[mtu]; 
            #region 
            {
                int count = 0;
                timer = new System.Timers.Timer();
                timer.Interval = 1000;
                timer.Elapsed += (s, e) =>
                {
                    if (count >= 5)
                    {
                        if (!Connectioned)//如果5秒后还未连接，则退出连接操作
                        {
                            Console.WriteLine("connecte filad!");
                            CancelTransmit();
                        } 
                        count = 0;
                        timer.Enabled = false;
                        timer.Dispose();
                    }
                    count++;
                };
                timer.Enabled = true;
            }
            #endregion
        }

        private void WsClient_OnMessage(object sender, MessageEventArgs e)
        {
            if (e.RawData.Length < FilePacket.HeaderLength) return;
            FilePacket fp = new FilePacket(e.RawData);
            switch (fp.CommandType)
            {
                case (byte)FileServerCommandType.Set:
                    {
                        if (FS == null)
                        {
                            FS = new FileStream(TFileInfo.fullName, FileMode.Open, FileAccess.Read, FileShare.Read);
                            OnTransmitBefore();
                        }
                        if (buffer.Length > FS.Length - TFileInfo.CurrLength)
                            buffer = new byte[FS.Length - TFileInfo.CurrLength];
                        FS.Read(buffer, 0, buffer.Length); 
                        fp.Payload = buffer;
                        TFileInfo.CurrLength += buffer.Length;
                        wsClient.Send(fp.ToArray());
                        OnTransmitting();
                        Console.WriteLine("上传:"+TFileInfo.Length.ToString() + ":" + TFileInfo.CurrLength.ToString());
                    }
                    break;
                case (byte)FileServerCommandType.Get:
                    {
                        if (FS == null)//打开文件
                            FS = new FileStream(CacheFile, FileMode.Append, FileAccess.Write, FileShare.Read); 
                        FS.Write(fp.Payload, 0, fp.PayloadLength);
                        TFileInfo.CurrLength += fp.PayloadLength;
                        wsClient.Send(fp.Header);
                        OnTransmitting(); 
                        if(TFileInfo.CurrLength >=TFileInfo.Length)
                            OnTransmited();
                    }
                    break;
                case (byte)FileServerCommandType.Else:
                    {
                        OnElseTransmiting();
                    }
                    break;
                case (byte)FileServerCommandType.Over:
                    {
                        OnTransmited();
                    }
                    break;
            }
        }

        private void OnTransmited()
        {
            if (!IsSend)
            {
                CloseFileStream();
                if (File.Exists(TFileInfo.fullName))
                {
                    File.Delete(TFileInfo.fullName);
                    System.Threading.Thread.Sleep(500);
                }
                if (File.Exists(CacheFile))
                    File.Move(CacheFile, TFileInfo.fullName);//拷贝文件
            }
            CancelTransmit();
            Console.WriteLine("over!");
            OnTransmitted();//触发文件传输完成事件
        }

        private void WsClient_OnOpen(object sender, EventArgs e)
        {
            Connectioned = true;
            Console.WriteLine("conneced!");
            if (IsSend)//如果是上传文件
            {
                FilePacket fp = new FilePacket();
                fp.CommandType = (byte)FileServerCommandType.New;
                BinaryFileMsg fmsg = new BinaryFileMsg();
                fmsg.MD5 = TFileInfo.MD5;
                fmsg.Extension = TFileInfo.Extension;
                fmsg.Length = TFileInfo.Length;
                fp.Payload = fmsg.Header;
                wsClient.Send(fp.ToArray());
            }
            else//如果是下载文件
            {
                RequestSendFilePak();//如果是下载文件，则开始下载
            }
        }

        private void WsClient_OnClose(object sender, CloseEventArgs e)
        {
            Console.WriteLine("conn close !");
        } 
        #endregion

        #endregion

        #region 方法

        #region  请求发送文件数据包
        /// <summary>
        /// 请求发送文件数据包
        /// </summary>
        private void RequestSendFilePak()
        {
            FilePacket fp = new FilePacket();
            fp.CommandType = (byte)FileServerCommandType.Get;
            if (FS == null)
            {
                BinaryFileMsg fileMsg = new BinaryFileMsg();
                fileMsg.MD5 = TFileInfo.MD5;//要下载的文件MD5值
                fileMsg.Extension = TFileInfo.Extension;
                fp.Payload = fileMsg.Header;
            }
            wsClient.Send(fp.ToArray());
        }
        #endregion

        #region 取消文件传输
        /// <summary>
        /// 取消文件传输
        /// </summary>
        public void CancelTransmit()
        {
            if (wsClient != null)
            {
                wsClient.Close();
                wsClient = null;
            }
            CloseFileStream();
            if (timer != null)
            {
                timer.Enabled = false; timer.Close(); timer.Dispose(); timer = null;
            }
        }
        #endregion

        #endregion
    }
}
